package com.ac.api.component.controller;

import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.base.annotation.SysLog;
import com.base.annotation.Unsecured;
import com.base.context.Context;
import com.base.context.ContextHolder;
import com.base.helper.BaseController;
import com.base.helper.DateUtils;
import com.base.helper.FileUploadUtils;
import com.base.helper.Result;
import com.ac.api.component.dao.CpAttachmentMapper;
import com.ac.api.component.entity.CpAttachment;
import com.ac.api.component.entity.CpPhoto;
import com.ac.api.component.service.CpAttachmentService;
import com.ac.api.component.vo.CpAttachmentVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author mzl
 * @since 2020-07-17
 */
@Api(tags = "个人附件管理")
@RestController
@RequestMapping("/enAttachment")
public class CpAttachmentController extends BaseController {

    private static final Logger              LOG = LoggerFactory.getLogger(CpAttachmentController.class);
    @Autowired
    private CpAttachmentService entityService;
    @Autowired
    private CpAttachmentMapper  entityMapper;
    private String BUCKET_NAME="guojunjie";
    @Autowired
    private OSS ossClient;
    @Autowired
    private CpAttachmentMapper cpAttachmentMapper;


    @SysLog(action = "enAttachment:findByPage", value = "附件管理：附件列表")
    @ApiOperation(value = "分页查询附件", notes = "分页查询附件")
    @RequestMapping(method = RequestMethod.GET)
    @ApiImplicitParams({@ApiImplicitParam(name = "size", value = "分页大小", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页面：从1开始", paramType = "query")})
    public Result<IPage<CpAttachment>> findByPage(final CpAttachmentVo example, final Page page) {
        IPage<CpAttachmentVo> records = entityService.findByPage(example, page);
        return new Result(true, records);
    }

//    @SysLog(action = "enAttachment:one", value = "附件管理：查询")
//    @ApiOperation(value = "查询单个附件")
//    @RequestMapping(value = "{id}", method = {RequestMethod.GET})
//    @ApiImplicitParam(name = "id", value = "附件ID", required = true, paramType = "path")
//    public Result one(@PathVariable final Integer id) {
//        CpAttachmentVo entity = entityMapper.findAttachmentById(id);
//        return new Result(true, entity);
//    }

    @SysLog(action = "enAttachment:add", value = "附件管理：添加")
    @ApiOperation(value = "添加附件")
    @RequestMapping(method = {RequestMethod.POST})
    public Result add(@Valid @RequestBody final CpAttachmentVo entity) {
        CpAttachmentVo cpAttachmentVo=entityService.saveAttachment(entity);
        if (null == cpAttachmentVo) {
            return new Result(false, "","无法找到对应模块和标签");
        }
        return new Result(true, "成功保存附件", null);
    }

    @SysLog(action = "enAttachment:update", value = "附件管理：修改")
    @ApiOperation(value = "修改附件")
    @RequestMapping(method = {RequestMethod.PUT})
    public Result update(@Valid @RequestBody final CpAttachmentVo entity) {
        if (null == entity.getId()) {
            throw new RuntimeException("id不能为空");
        }
        CpAttachmentVo cpAttachmentVo=entityService.updateAttachment(entity);
        if (null == cpAttachmentVo) {
            return new Result(false, "","无法找到对应模块和标签");
        }
        return new Result(true, "成功修改附件", null);
    }

//    @SysLog(action = "one", value = "查询单个附件")
    @ApiOperation(value = "查询单个附件")
    @RequestMapping(value = "{id}", method = {RequestMethod.GET})
    @ApiImplicitParam(name = "id", value = "附件ID", required = true, paramType = "path")
    public Result one(@PathVariable final Integer id) {
        try {
            CpAttachmentVo entity = cpAttachmentMapper.findAttachmentById(id);
            return new Result(true, entity);
        } catch (Exception e) {
            LOG.error("查询单个图片失败", e);
            return new Result(false, new CpPhoto());
        }
    }


    @Unsecured
    @ApiOperation(value = "私密附件上传, 返回附件全部信息")
    @RequestMapping(value = "upload", method = RequestMethod.POST)
    public Result<CpAttachment> upload(@RequestParam("file") MultipartFile file) {
        Context context = ContextHolder.currentContext();
        String  oriname = file.getOriginalFilename();
        try {
            String convertedName = new String(oriname.getBytes("ISO8859_1"), "UTF-8");
            long   size          = file.getSize();
            LOG.info("原文件名：{}, 大小: {}", convertedName, size);
            //
            String code     = UUID.randomUUID().toString().replaceAll("-", "");
            String filePath = FileUploadUtils.uploadFile(file,"Attachment\\"+DateUtils.date(new Date(), "yyyyMMdd"), code);
            if (null == filePath) {
                throw new RuntimeException("保存文件失败");
            }
            CpAttachment cpAttachment = new CpAttachment();
            cpAttachment.setUserid(context.currentUser().getId());
            cpAttachment.setName(convertedName);
            cpAttachment.setType(file.getContentType());
            cpAttachment.setPath(filePath);
            cpAttachment.setCode(code);
            cpAttachment.setSize(size + "");
            cpAttachment.setCreatetime(new Date());
            cpAttachment.setState("t");
            entityService.save(cpAttachment);
            cpAttachment = entityService.findByCode(code);
            return new Result(true, cpAttachment);
        } catch (Exception e) {
            LOG.error("保存文件失败", e);
            return new Result(false, "上传文件失败", e.getMessage());
        }
    }

    @Unsecured
    @ApiOperation(value = "公开附件上传,仅返回附件路径，需指定type,图片picture，视频video")
    @RequestMapping(value = "uploadByType", method = RequestMethod.POST)
    public Result<String> uploadByType(@RequestParam("file") MultipartFile file,@RequestParam("type") String type) {
        if(!(type.equals("picture") ||type.equals("video"))) {
            return new Result(false, "请输入正确的文件type");
        }
        String  oriname = file.getOriginalFilename();
        try {
            String convertedName = new String(oriname.getBytes("ISO8859_1"), "UTF-8");
            long   size          = file.getSize();
            LOG.info("原文件名：{}, 大小: {}", convertedName, size);
            //
            String code     = UUID.randomUUID().toString().replaceAll("-", "");
            String filePath = FileUploadUtils.uploadFile(file, type+"\\"+DateUtils.date(new Date(), "yyyyMMdd"), code);
            if (null == filePath) {
                throw new RuntimeException("保存文件失败");
            }
            return new Result(true, filePath);
        } catch (Exception e) {
            LOG.error("保存文件失败", e);
            return new Result(false, "上传文件失败", e.getMessage());
        }
    }




    @Unsecured
    @ApiOperation(value = "批量文件下载")
    @RequestMapping(value = "downloadFiles/{ids}", method = RequestMethod.GET)
    @ApiImplicitParam(name = "ids", value = "附件ID", required = true, paramType = "path")
    public void downloadFiles(@PathVariable("ids") final List<Integer> ids, HttpServletResponse response) {
        if (null == ids || ids.size() == 0) {
            LOG.error("下载错误", "没有找到id");
        }
        List<CpAttachment> cpAttachments = entityService.findByIds(ids);
        Map<String, File>  files         = new HashMap<>();
        for (CpAttachment cpAttachment : cpAttachments) {
            files.put(cpAttachment.getName(), new File(cpAttachment.getPath()));
        }
        ZipOutputStream zos   = null;
        ZipEntry        entry = null;
        FileInputStream in    = null;
        try (OutputStream out = response.getOutputStream();) {
            response.setContentType("application/x-zip-compressed");
            response.setCharacterEncoding("UTF-8");
            response.addHeader("Content-Disposition", "attachment;filename=\"" +
                    new String(("附件" + DateUtils.date(new Date()) + ".zip").getBytes("utf-8"), "ISO8859_1") + "\"");
            zos = new ZipOutputStream(out);
            for (String fileName : files.keySet()) {
                byte[] buffer = new byte[1024];
                int    len;
                //创建zip订单（一个文件对应一个ZipEntry）
                entry = new ZipEntry(fileName);
                in = new FileInputStream(files.get(fileName));
                zos.putNextEntry(entry);
                //文件流循环写入ZipOutputStream
                while ((len = in.read(buffer)) != -1) {
                    zos.write(buffer, 0, len);
                }
                zos.closeEntry();
                in.close();
            }
            zos.close();
        } catch (Exception e) {
            LOG.error("批量下载错误", e.getMessage());
        }
    }

    @ApiOperation(value = "获取OSS Url临时签名")
    @GetMapping("/getOssSignal")
    public Result<String> generatePresignedURL() {
        long EXPIRE_TIME = 3600 * 1000L;
        String OBJECT_NAME = System.currentTimeMillis()+"";
        try {
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(BUCKET_NAME, OBJECT_NAME, HttpMethod.PUT);
            Date expiration = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            request.setExpiration(expiration);
            request.setContentType("image/png");
            URL signedUrl = ossClient.generatePresignedUrl(request);
            return new Result(true, signedUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

//    @SysLog(action = "enAttachment:delete", value = "附件管理：删除")
//    @ApiOperation(value = "删除附件")
//    @RequestMapping(value = "{id}", method = {RequestMethod.DELETE})
//    @ApiImplicitParam(name = "id", value = "附件ID", required = true, paramType = "path")
//    public Result delete(@PathVariable final Integer id) {
//        entityService.removeById(id);
//        return new Result(true, "成功删除附件", null);
//    }


    //    @SysLog(action = "enAttachment:all", value = "附件管理：全部附件")
//    @ApiOperation(value = "全部附件")
//    @RequestMapping(value = "all", method = RequestMethod.GET)
//    public Result<List<CpAttachment>> all(CpAttachment example) {
//        List<CpAttachment> entitys = entityService.list(example);
//        if (null != entitys) {
//            return new Result<>(true, entitys);
//        }
//        return new Result<>(true, Collections.emptyList());
//    }


//    @Unsecured
//    @ApiOperation(value = "文件下载")
//    @RequestMapping(value = "download/{id}", method = RequestMethod.GET)
//    @ApiImplicitParam(name = "id", value = "附件ID", required = true, paramType = "path")
//    public Result<Void> download(@PathVariable("id") final Integer id, HttpServletResponse response) {
//        CpAttachment cpAttachment = entityService.getById(id);
//        if (null == cpAttachment || "0".equals(cpAttachment.getState())) {
//            throw new RuntimeException("没有找到id对应的对象");
//        }
//        File                file   = new File(cpAttachment.getPath());
//        byte[]              buffer = new byte[1024];
//        FileInputStream     fis    = null;
//        BufferedInputStream bis    = null;
//        try (OutputStream out = response.getOutputStream();) {
//            response.setContentType(cpAttachment.getType());
//            response.setCharacterEncoding("UTF-8");
//            response.addHeader("Content-Disposition", "attachment;filename=\"" +
//                    new String((cpAttachment.getName()).getBytes("utf-8"), "ISO8859_1") + "\"");
//            // 将创建的Excel对象利用二进制流的形式强制输出到客户端去
//            fis = new FileInputStream(file);
//            bis = new BufferedInputStream(fis);
//            int i = bis.read(buffer);
//            while (i != -1) {
//                out.write(buffer);
//                i = bis.read(buffer);
//            }
//            // 强制将数据从内存中保存
//            out.flush();
//        } catch (IOException e) {
//            return new Result<>(false, "文件下载失败", e.getMessage());
//        }
//        return new Result<>(true, "文件下载完成", null);
//    }



}

